/************************************************************
* author: alexander.aivars <alexander.aivars&#64;svt.se>
* $Date:2007-12-19 11:39:12 +0100 (Wed, 19 Dec 2007) $
* $Revision:196 $
* $HeadURL:svn://stoiis03.internt.svt.se/SVTiFLASH/trunk/SVTSE/Source/Classes/se/svt/web/net/XMLDB.as $
* $Id:XMLDB.as 196 2007-12-19 10:39:12Z alai $
************************************************************/
package se.svt.web.net
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLVariables;
	
	import se.svt.web.events.NetDataRequestEvent;
	import se.svt.web.models.XMLDBData;
	
	/**
	* Dispatched when data has finished loading.
	*
	* @eventType se.svt.web.events.NetDataRequestEvent.COMPLETE
	*/
	[Event(name="NetDataRequstComplete", type="se.svt.web.events.NetDataRequestEvent")]

	/**
	* Dispatched when data has loaded successfully.
	*
	* @eventType se.svt.web.events.NetDataRequestEvent.
	*/
	[Event(name="NetDataRequstSuccess", type="se.svt.web.events.NetDataRequestEvent")]

	/**
	* Dispatched when data has loaded with error response.
	*
	* @eventType se.svt.web.events.NetDataRequestEvent.
	*/
	[Event(name="NetDataRequstFailed", type="se.svt.web.events.NetDataRequestEvent")]

	/**
	* Dispatched when an error occurs that causes a load operation to fail.
	*
	* @eventType se.svt.web.events.NetDataRequestEvent.
	*/
	[Event(name="NetDataRequstError", type="se.svt.web.events.NetDataRequestEvent")]
	

	/**
	 * 
	 * @author Alexander Aivars
	 * 
	 */	
	public class XMLDB extends EventDispatcher
	{
		
		private static const SET_URL:String = "http://svt.se/svttools/storeExternalData.jsp";
		private static const GET_URL:String = "http://svt.se/svttools/getExternalData.jsp";
		private var _applicationId:String;
		private var _model:XMLDBData;

		private function initialize(applicationId:String):void 
		{
			_applicationId = applicationId;
					
		}
		
		private function reset():void 
		{
			_model = null;
		}
		
		private function ioErrorHandler(event:IOErrorEvent):void {
            dispatchEvent(new NetDataRequestEvent(NetDataRequestEvent.ERROR));
        }
		
		private function addPostListners(dispatcher:IEventDispatcher):void {
            dispatcher.addEventListener(Event.COMPLETE, postComplete);
            dispatcher.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
        }
		
		private function removePostListners(dispatcher:IEventDispatcher):void {
            dispatcher.removeEventListener(Event.COMPLETE, postComplete);
            dispatcher.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
        }

		private function addLoadListners(dispatcher:IEventDispatcher):void {
            dispatcher.addEventListener(Event.COMPLETE, loadComplete);
            dispatcher.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
        }

		private function removeLoadListners(dispatcher:IEventDispatcher):void {
            dispatcher.removeEventListener(Event.COMPLETE, loadComplete);
            dispatcher.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
        }

		private function postComplete(event:Event):void {
            var loader:URLLoader = event.target as URLLoader;
			var response:Namespace  = new Namespace("http://svt.se/xmlnamespaces/svtFlash/externalDataResponse/");

			var xml:XML = new XML(loader.data);
            if(!xml..response::error.toString() && xml..response::dataHashkey.toString()) {
            	_model.dataHashkey = xml..response::dataHashkey.toString();
            	dispatchEvent(new NetDataRequestEvent(NetDataRequestEvent.SUCCESS));
            	
            } else {
            	_model.dataHashkey = "-1";
            	dispatchEvent(new NetDataRequestEvent(NetDataRequestEvent.FAILED));
            }

			dispatchEvent(new NetDataRequestEvent(NetDataRequestEvent.COMPLETE));

            reset();
            removePostListners(loader);
        }
		
		private function loadComplete(event:Event):void {
            var loader:URLLoader = event.target as URLLoader;
			var response:Namespace  = new Namespace("http://svt.se/xmlnamespaces/svtFlash/externalDataResponse/");

			var xml:XML = new XML(loader.data);

			if(xml..response::dataHashkey.@value != "") {
				_model.setVariables(parseInt(xml..response::articleId.@value.toString()),
									parseInt(xml..response::departmentId.@value.toString()),
									decodeURI(xml..response::userid.@value.toString()),
									decodeURI(xml..response::data.toString()),
									parseInt(xml..response::state.@value.toString()),
									xml..response::dataHashkey.@value.toString());
				dispatchEvent(new NetDataRequestEvent(NetDataRequestEvent.SUCCESS));
			} else {
				dispatchEvent(new NetDataRequestEvent(NetDataRequestEvent.FAILED));
			}

				dispatchEvent(new NetDataRequestEvent(NetDataRequestEvent.COMPLETE));

            reset();
            removeLoadListners(loader);
        }
		
		/**
		 * Creates a new XMLDB instance.
		 * @param applicationId A reference id of the application using XMLDB data. 
		 * 
		 */
		public function XMLDB(applicationId:String)
		{
			initialize(applicationId);
		}

		/**
		 * HTTP post data to be stored. 
		 * The data model will be updated with a refernece dataHashkey when the http post is succesfully completed.
		 * 
		 * @param model
		 * 
		 */
		public function post(model:XMLDBData):void 
		{
			if(_model != null) {
				throw new Error("Data model already waiting for data");
			} else {
				_model = model;
			}
			
			var loader:URLLoader = new URLLoader();
            var request:URLRequest = new URLRequest(SET_URL);
            var variables:URLVariables = new URLVariables();

			variables.applicationName = _applicationId;
			
			if(model.articleId) variables.articleId = model.articleId;
			if(model.departmentId) variables.departmentId = model.departmentId;
			if(model.userId) variables.userId = model.userId;
			if(model.data) variables.data = encodeURI(model.data);
			if(model.state) variables.state = model.state;

			
			request.data = variables;
			addPostListners(loader);
			
            try {
            	try {
	                loader.load(request);
            	} catch (error:SecurityError) { 
            		//trace("SecurityError post xmlDb.");
            		reset();
	            	throw error;
            	}
            } catch (error:Error) {
                // trace(error.name +" : Unable to load requested document.");
        		reset();
            	throw error;	
            }      			
		}
		
		/**
		 * Load data model values. Data model requers a correct dataHashkey.
		 * 
		 * @param model
		 * 
		 */
		public function load(model:XMLDBData):void
		{
			if(model.dataHashkey == null) {
				throw new Error("Model requires hashkey to load");				
			} else {
				if(_model != null) {
					throw new Error("Data model already waiting for data");
				} else {
					_model = model;
				}
				
				var loader:URLLoader = new URLLoader();
	            var request:URLRequest = new URLRequest(GET_URL);
	            var variables:URLVariables = new URLVariables();			
				
				variables.dataHashkey = model.dataHashkey;

				request.data = variables;
				addLoadListners(loader);

	            try {
	            	try {
		                loader.load(request);
	            	} catch (error:SecurityError) { 
	            		//trace("SecurityError post xmlDb.");
	            		reset();
		            	throw error;
	            	}
	            } catch (error:Error) {
	                // trace(error.name +" : Unable to load requested document.");
	        		reset();
	            	throw error;	
	            }  
            			
			}
		}

	}
}